package com.eatme.core.design.pattern.creational.singleton;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//        LazySingleton lazySingleton = LazySingleton.getInstance();

//        Thread t1 = new Thread(new T());
//        Thread t2 = new Thread(new T());
//        t1.start();
//        t2.start();
//        System.out.println("program end");

//        HungrySingleton instance = HungrySingleton.getInstance();
//        ObjectOutput oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
//        oos.writeObject(instance);
//        File file = new File("singleton_file");
//        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
//        HungrySingleton newInstance = (HungrySingleton) ois.readObject();
//
//        System.out.println(instance);
//        System.out.println(newInstance);
//        System.out.println(instance == newInstance);

//        Class objectClass = HungrySingleton.class;
//        Class objectClass = StaticInnerClassSingleton.class;
        Class objectClass = LazySingleton.class;
        Constructor constructor =objectClass.getDeclaredConstructor();
        constructor.setAccessible(true); //修改构造objectClass器权限

        LazySingleton newInstance = (LazySingleton) constructor.newInstance();
        LazySingleton instance = LazySingleton.getInstance();


//        StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
//        StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();

//        HungrySingleton instance =HungrySingleton.getInstance();
//        HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();

        System.out.println(instance);
        System.out.println(newInstance);
        System.out.println(instance == newInstance);


        // 枚举的序列化 反射攻击
        EnumInstance enumInstance = EnumInstance.INSTANCE;
        enumInstance.setData(new Object());
        ObjectOutput oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
        oos.writeObject(enumInstance);
        File file = new File("singleton_file");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        EnumInstance newEnumInstance = (EnumInstance) ois.readObject();


        Class enumClass = EnumInstance.class;

        // 枚举类没有无参构造器
        Constructor enumConstructor =enumClass.getDeclaredConstructor(String.class,int.class);
        constructor.setAccessible(true); //修改构造objectClass器权限

         // EnumInstance constructorInstance = (EnumInstance) enumConstructor.newInstance("dk",666);

        System.out.println(enumInstance.getData());
        System.out.println(newEnumInstance.getData());
        System.out.println(enumInstance.getData() == newEnumInstance.getData());

        EnumInstance instance1 = EnumInstance.getInstance();
        instance1.printTest();


        // 容器单例
//        Thread t1 = new Thread(new T());
//        Thread t2 = new Thread(new T());
//        t1.start();
//        t2.start();

        // 线程单例
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());


        Thread t1 = new Thread(new T());
        Thread t2 = new Thread(new T());
        t1.start();
        t2.start();





    }
}
